﻿using Microsoft.EntityFrameworkCore;
using QMERP.Domain.Entities;
using QMERP.Infrastructure.Extensions;
using QMERP.Infrastructure.Security;
using QMERP.SeedWork;

namespace QMERP.Infrastructure.EFCore
{
    public partial class QMERPDbContext : DbContext
    {
        //protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        //{
        //    string dbConnectionString="Data Source=.;Initial Catalog=System;User ID=sa;Password=19911004";
        //    // 定义要使用的数据库
        //    optionsBuilder.UseSqlServer(dbConnectionString);
        //}
        private readonly ICurrentUser _currentUser;
        public QMERPDbContext(DbContextOptions<QMERPDbContext> options, ICurrentUser currentUser) : base(options)
        {
            _currentUser = currentUser;
        }

        public virtual DbSet<App> App { get; set; }
        public virtual DbSet<Attachment> Attachment { get; set; }
        public virtual DbSet<Contract> Contract { get; set; }
        public virtual DbSet<Contract_Customer> Contract_Customer { get; set; }
        public virtual DbSet<Contract_Lens> Contract_Lens { get; set; }
        public virtual DbSet<Contract_Lens_SalesProcessConstraint> Contract_Lens_SalesProcessConstraint { get; set; }
        public virtual DbSet<Currency> Currency { get; set; }
        public virtual DbSet<Customer> Customer { get; set; }
        public virtual DbSet<Dictionary> Dictionary { get; set; }
        public virtual DbSet<DictionaryCategory> DictionaryCategory { get; set; }
        public virtual DbSet<Lens> Lens { get; set; }
        public virtual DbSet<Lens_SalesProcessConstraint> Lens_SalesProcessConstraint { get; set; }
        public virtual DbSet<Lens_Supplier> Lens_Supplier { get; set; }
        public virtual DbSet<LogOperate> LogOperate { get; set; }
        public virtual DbSet<LogSignIn> LogSignIn { get; set; }
        public virtual DbSet<Organization> Organization { get; set; }
        public virtual DbSet<Organization_Role> Organization_Role { get; set; }
        public virtual DbSet<Privilege> Privilege { get; set; }
        public virtual DbSet<Role> Role { get; set; }
        public virtual DbSet<RetailOrder> RetailOrder { get; set; }
        public virtual DbSet<RetailOrderDetail> RetailOrderDetail { get; set; }
        public virtual DbSet<BulkOrder> BulkOrder { get; set; }
        public virtual DbSet<BulkOrderDetail> BulkOrderDetail { get; set; }
        public virtual DbSet<BulkOrderDetail_LensDetail> BulkOrderDetail_LensDetail { get; set; }
        public virtual DbSet<BulkOrderDetail_MonofocalMaterialDetail> BulkOrderDetail_MonofocalMaterialDetail { get; set; }
        public virtual DbSet<BulkOrderDetail_BifocalMaterialDetail> BulkOrderDetail_BifocalMaterialDetail { get; set; }
        public virtual DbSet<SalesProcess> SalesProcess { get; set; }
        public virtual DbSet<SerialNumber> SerialNumber { get; set; }
        public virtual DbSet<Stock> Stock { get; set; }
        public virtual DbSet<StockDetail> StockDetail { get; set; }
        public virtual DbSet<StockActionLog> StockActionLog { get; set; }
        public virtual DbSet<StockActionLogDetail> StockActionLogDetail { get; set; }
        public virtual DbSet<StockActionStatisticsLog> StockActionStatisticsLog { get; set; }
        public virtual DbSet<StockActionStatisticsLogDetail> StockActionStatisticsLogDetail { get; set; }
        public virtual DbSet<PurchaseOrder> PurchaseOrder { get; set; }
        public virtual DbSet<PurchaseOrderDetail> PurchaseOrderDetail { get; set; }
        public virtual DbSet<PurchaseOrderDetail_LensDetail> PurchaseOrderDetail_LensDetail { get; set; }
        public virtual DbSet<TransferLensOrder> TransferLensOrder { get; set; }
        public virtual DbSet<TransferLensOrderDetail> TransferLensOrderDetail { get; set; }
        public virtual DbSet<TransferLensOrderDetail_LensDetail> TransferLensOrderDetail_LensDetail { get; set; }
        public virtual DbSet<TransferOrder> TransferOrder { get; set; }
        public virtual DbSet<TransferOrderDetail> TransferOrderDetail { get; set; }
        public virtual DbSet<TransferOrderDetail_LensDetail> TransferOrderDetail_LensDetail { get; set; }
        public virtual DbSet<InventoryOrder> InventoryOrder { get; set; }
        public virtual DbSet<InventoryOrderDetail> InventoryOrderDetail { get; set; }
        public virtual DbSet<InventoryOrderDetail_LensDetail> InventoryOrderDetail_LensDetail { get; set; }
        public virtual DbSet<EnterStockOrder> EnterStockOrder { get; set; }
        public virtual DbSet<EnterStockOrderDetail> EnterStockOrderDetail { get; set; }
        public virtual DbSet<EnterStockOrderDetail_LensDetail> EnterStockOrderDetail_LensDetail { get; set; }
        public virtual DbSet<LeaveStockOrder> LeaveStockOrder { get; set; }
        public virtual DbSet<LeaveStockOrderDetail> LeaveStockOrderDetail { get; set; }
        public virtual DbSet<LeaveStockOrderDetail_LensDetail> LeaveStockOrderDetail_LensDetail { get; set; }
        public virtual DbSet<Supplier> Supplier { get; set; }
        public virtual DbSet<User> User { get; set; }
        public virtual DbSet<User_Organization> User_Organization { get; set; }
        public virtual DbSet<User_Role> User_Role { get; set; }
        public virtual DbSet<Warehouse> Warehouse { get; set; }



        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            //自动映射
            modelBuilder.ApplyAllConfigurations(System.Reflection.Assembly.GetExecutingAssembly());
            //foreach (var entityType in modelBuilder.Model.GetEntityTypes())
            //{
            //    entityType.GetOrAddProperty("IsEnable", typeof(bool));
            //    var parameter = Expression.Parameter(entityType.ClrType);
            //    var propertyMethodInfo = typeof(EF).GetMethod("Property").MakeGenericMethod(typeof(bool));
            //    var isDeletedProperty = Expression.Call(propertyMethodInfo, parameter, Expression.Constant("IsEnable"));
            //    BinaryExpression compareExpression = Expression.MakeBinary(ExpressionType.Equal, isDeletedProperty, Expression.Constant(true));
            //    var lambda = Expression.Lambda(compareExpression, parameter);
            //    modelBuilder.Entity(entityType.ClrType).HasQueryFilter(lambda);
            //}
        }
        public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
        {
            var changedEntities = SetDefaultFields();

            //没有自动开启事务的情况下,保证主从表插入，主从表更新开启事务。
            var isManualTransaction = false;

            if (!Database.AutoSavepointsEnabled && Database.CurrentTransaction is null && changedEntities > 1)
            {
                isManualTransaction = true;
                Database.AutoSavepointsEnabled = true;
            }

            var result = base.SaveChangesAsync(cancellationToken);

            //如果手工开启了自动事务，用完后关闭。
            if (isManualTransaction)
                Database.AutoSavepointsEnabled = false;

            return result;
        }
        protected virtual int SetDefaultFields()
        {
            var allBasicAuditEntities = ChangeTracker.Entries<ICreateEntity<long>>().Where(x => x.State == EntityState.Added);
            foreach (var entity in allBasicAuditEntities)
            {
                entity.Entity.CreatedBy = _currentUser.Id;
                entity.Entity.CreatedByName = _currentUser.Name;
                entity.Entity.CreatedOn = DateTime.Now;
            }
            var auditFullEntities = ChangeTracker.Entries<IUpdateEntity<long>>().Where(x => x.State == EntityState.Modified || x.State == EntityState.Unchanged);
            foreach (var entity in auditFullEntities)
            {
                entity.Entity.UpdatedBy = _currentUser.Id;
                entity.Entity.UpdatedByName = _currentUser.Name;
                entity.Entity.UpdatedOn = DateTime.Now;
            }
            return ChangeTracker.Entries<Entity>().Count();
        }
    }
}
